#pragma once

#include <string>
#include <memory>
#include <cstdint>
#include "../corelib/object_pool.hpp"

namespace kratos { namespace engine {

class Component;
class ComponentVersion;
class ComponentTracker;
class ComponentManager;
class ComponentFactory;

// Component
class Component {
public:
    // Returns component name
    // @retval component name
    virtual const std::string& getName() const  = 0;
    // Returns component's factory
    // @retval component's factory
    virtual ComponentFactory* getFactory() = 0;
    // Tracks component's lifecycle event
    // @param tracker @see ComponentTracker
    // @retval true
    // @retval false fail
    virtual bool track(ComponentTracker* tracker) = 0;
    // Untracks component's lifecycle event
    // @param tracker @see ComponentTracker
    // @retval true
    // @retval false fail
    virtual bool untrack(ComponentTracker* tracker) = 0;
    // Invoking by component manager when erase the root component
    virtual void onErase() = 0;
    // Returns ComponentVersion
    virtual const ComponentVersion& getVersion() = 0;
};

// Component version
class ComponentVersion {
public:
    // Returns version string
    virtual const std::string& getVersion() const = 0;
    // Returns full version string
    virtual const std::string& getFullVersion() const = 0;
};

// Component factory
class ComponentFactory {
public:
    virtual ~ComponentFactory() {}
    // Destroy component
    // @param component component pointer
    virtual void destroy(Component* component) = 0;
};

// Component lifecycle event tracker
class ComponentTracker {
public:
    // Invoking by component when component has been unregistered
    // @param name component name
    virtual void onVanish(const std::string& name) = 0;
};

// Component manager
class ComponentManager {
public:
    // Registers a component
    // @param ptr component pointer
    // @retval true
    // @retval false fail
    virtual bool registerComponent(Component* ptr) = 0;
    // Unregisters a component
    // @param name component name
    // @retval true
    // @retval false fail
    virtual bool unregisterComponent(const std::string& name) = 0;
    // Returns the root component's shared pointer
    // @param name component name
    // @return The root component's shared pointer
    virtual std::shared_ptr<Component> get(const std::string& name) = 0;
};

}}
